import { Button } from 'antd';
import { useEffect, useMemo, useRef, useState } from 'react';

import { AntdTabs } from '@/components/eai-design';
import { SvgIcon } from '@/components/icon';
import Markdown from '@/components/markdown';
import { KnowledgeBaseApprovalStore } from '@/store/knowledgeBaseApproval';
import { formatData } from '@/utils/time';

const DocumentMessage = () => {
  const {
    checkoutList,
    wronglyDataList,
    sensitiveDataList,
    showTitle,
    setShowTitle,
    repetitionDataList,
  } = KnowledgeBaseApprovalStore();

  const optimizeTypes: string[] = useMemo(() => {
    return Array.isArray(checkoutList) && checkoutList.length > 0
      ? checkoutList[0]?.optimize_text || []
      : [];
  }, [checkoutList]);

  const hasWrong = useMemo(
    () => optimizeTypes.some((t) => String(t).includes('错别字')),
    [optimizeTypes],
  );
  const hasSensitive = useMemo(
    () => optimizeTypes.some((t) => String(t).includes('敏感词')),
    [optimizeTypes],
  );
  const hasRepetition = useMemo(
    () =>
      optimizeTypes.some((t) => String(t).includes('重复')) ||
      (repetitionDataList?.length || 0) > 0,
    [optimizeTypes, repetitionDataList],
  );

  const previewRef = useRef<HTMLDivElement>(null);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const [activeTab, setActiveTab] = useState<'sensitive' | 'wrong' | 'repetition'>(
    hasSensitive ? 'sensitive' : hasWrong ? 'wrong' : 'repetition',
  );

  const wronglyList = wronglyDataList?.auto_correct_pairs_with_count || [];
  const wronglyTrunks = wronglyDataList?.trunks || [];

  const sensitiveList =
    (sensitiveDataList as any)?.all_sensitive_words_with_count ||
    (sensitiveDataList as any)?.auto_correct_pairs_with_count ||
    [];
  const sensitiveTrunks = (sensitiveDataList as any)?.trunks || [];

  const getKeyword = (item: any): string =>
    item?.word || item?.correctedText || item?.originalText || '';

  // 全角/半角宽度无关归一化
  const normalizeWidthToken = (s: string) =>
    Array.from(s || '')
      .map((ch) => {
        const cp = ch.codePointAt(0) as number;
        if (cp === 0x3000) return ' ';
        if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
        return ch;
      })
      .join('');

  const escapeReg = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

  const currentList = activeTab === 'wrong' ? wronglyList : sensitiveList;
  const currentTrunks = activeTab === 'wrong' ? wronglyTrunks : sensitiveTrunks;

  useEffect(() => {
    if (!showTitle) return;
    setSelectedIndex(0);
  }, [showTitle, activeTab, wronglyList, sensitiveList]);

  const wordsForCurrent: any[] = useMemo(() => {
    if (activeTab === 'wrong') {
      const arr = (currentList || []).map((i: any) => i?.correctedText).filter(Boolean);
      const unique = Array.from(new Set(arr));
      return unique.sort((a: any, b: any) => b.length - a.length);
    }
    const arr = (currentList || []).map((i: any) => getKeyword(i)).filter(Boolean);
    const unique = Array.from(new Set(arr));
    return unique.sort((a: any, b: any) => b.length - a.length);
  }, [activeTab, currentList]);

  const currentTrunksSig = (currentTrunks || [])
    .map((c: any) => (c && typeof c.text === 'string' ? c.text : ''))
    .join('|');

  const globalMatches = useMemo(() => {
    if (!currentTrunks || !wordsForCurrent.length)
      return [] as Array<{ chunkIndex: number; word: string; localIndex: number }>;

    const toUnicodeEscape = (codePoint: number) =>
      codePoint <= 0xffff
        ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, '0')}`
        : `\\u{${codePoint.toString(16).toUpperCase()}}`;

    const buildWidthInsensitivePattern = (token: string) =>
      Array.from(token)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x20 || cp === 0x3000) {
            return `(?:${toUnicodeEscape(0x20)}|${toUnicodeEscape(0x3000)})`;
          }
          if (cp >= 0x21 && cp <= 0x7e) {
            const fw = cp + 0xfee0;
            return `(?:${escapeReg(ch)}|${toUnicodeEscape(fw)})`;
          }
          if (cp >= 0xff01 && cp <= 0xff5e) {
            const hw = cp - 0xfee0;
            return `(?:${toUnicodeEscape(cp)}|${escapeReg(String.fromCodePoint(hw))})`;
          }
          return escapeReg(ch);
        })
        .join('');

    const normalizeWidth = (s: string) =>
      Array.from(s)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x3000) return ' ';
          if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
          return ch;
        })
        .join('');

    const unique = Array.from(new Set(wordsForCurrent)).sort(
      (a: string, b: string) => b.length - a.length,
    );
    const pattern = new RegExp(unique.map((w) => buildWidthInsensitivePattern(w)).join('|'), 'gu');

    const matches: Array<{ chunkIndex: number; word: string; localIndex: number }> = [];
    currentTrunks.forEach((chunk: any, chunkIndex: number) => {
      const text: string = chunk?.text || '';
      if (!text) return;
      const localCounter: Record<string, number> = {};
      let m: RegExpExecArray | null;
      while ((m = pattern.exec(text)) !== null) {
        const word = m[0];
        const key = normalizeWidth(word);
        const idx = localCounter[key] ?? 0;
        matches.push({ chunkIndex, word, localIndex: idx });
        localCounter[key] = idx + 1;
      }
    });
    return matches;
  }, [currentTrunksSig, wordsForCurrent]);

  // 确保默认高亮为第一条匹配（红色），并在匹配数量变化时复位索引
  useEffect(() => {
    if (globalMatches.length === 0) {
      if (selectedIndex !== 0) setSelectedIndex(0);
      return;
    }
    if (selectedIndex >= globalMatches.length) {
      setSelectedIndex(0);
    }
  }, [globalMatches, selectedIndex]);

  // 计算“总出现次数”（独立于视图状态）
  const computeTotalByWords = (words: string[], trunks: any[]) => {
    if (!trunks || !words || words.length === 0) return 0;
    const pattern = new RegExp(words.map((w) => escapeReg(w)).join('|'), 'g');
    return trunks.reduce((sum: number, chunk: any) => {
      const text: string = chunk?.text || '';
      if (!text) return sum;
      const matches = text.match(pattern);
      return sum + (matches ? matches.length : 0);
    }, 0);
  };

  const wrongWordsAll = useMemo(() => {
    const arr = (wronglyList || []).map((i: any) => i?.correctedText).filter(Boolean);
    return Array.from(new Set(arr)).sort((a: string, b: string) => b.length - a.length);
  }, [wronglyList]);
  const sensitiveWordsAll: any[] = useMemo(() => {
    const arr = (sensitiveList || []).map((i: any) => getKeyword(i)).filter(Boolean);
    return Array.from(new Set(arr)).sort((a: any, b: any) => b.length - a.length);
  }, [sensitiveList]);

  const totalWrongMatches = useMemo(() => {
    const list = wronglyList || [];
    if (!list.length) return 0;
    const merged: Record<string, number> = {};
    list.forEach((i: any) => {
      const key = normalizeWidthToken(i?.correctedText || '');
      if (!key) return;
      merged[key] = (merged[key] || 0) + (i?.count || 0);
    });
    return Object.values(merged).reduce((a, b) => a + b, 0);
  }, [wronglyList]);

  const sensitiveTrunksSig = (sensitiveTrunks || [])
    .map((c: any) => (c && typeof c.text === 'string' ? c.text : ''))
    .join('|');
  const totalSensitiveMatches = useMemo(() => {
    const list = sensitiveList || [];
    if (!list.length) return 0;
    const merged: Record<string, number> = {};
    list.forEach((i: any) => {
      const key = normalizeWidthToken(getKeyword(i));
      if (!key) return;
      merged[key] = (merged[key] || 0) + (i?.count || 0);
    });
    return Object.values(merged).reduce((a, b) => a + b, 0);
  }, [sensitiveList]);

  // 滚动到当前选中匹配
  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    const timer = setTimeout(() => {
      const el = container.querySelector('#selected-highlight') as HTMLElement | null;
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
      }
    }, 0);
    return () => clearTimeout(timer);
  }, [selectedIndex, currentTrunks]);

  function highlightText(text: string, chunkIndex: number) {
    if (!wordsForCurrent.length) return text;

    const toUnicodeEscape = (codePoint: number) =>
      codePoint <= 0xffff
        ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, '0')}`
        : `\\u{${codePoint.toString(16).toUpperCase()}}`;

    const normalizeWidth = (s: string) =>
      Array.from(s)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x3000) return ' ';
          if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
          return ch;
        })
        .join('');

    const escapeForGroup = (s: string) => escapeReg(s);

    const buildWidthInsensitivePattern = (token: string) =>
      Array.from(token)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x20 || cp === 0x3000) {
            return `(?:${toUnicodeEscape(0x20)}|${toUnicodeEscape(0x3000)})`;
          }
          if (cp >= 0x21 && cp <= 0x7e) {
            const fw = cp + 0xfee0;
            return `(?:${escapeForGroup(ch)}|${toUnicodeEscape(fw)})`;
          }
          if (cp >= 0xff01 && cp <= 0xff5e) {
            const hw = cp - 0xfee0;
            return `(?:${toUnicodeEscape(cp)}|${escapeForGroup(String.fromCodePoint(hw))})`;
          }
          return escapeForGroup(ch);
        })
        .join('');

    const unique = Array.from(new Set(wordsForCurrent)).sort(
      (a: string, b: string) => b.length - a.length,
    );
    const pattern = new RegExp(unique.map((w) => buildWidthInsensitivePattern(w)).join('|'), 'gu');

    const selected = globalMatches[selectedIndex];
    const localCounter: Record<string, number> = {};

    return text.replace(pattern, (matched) => {
      const key = normalizeWidth(matched);
      const count = localCounter[key] ?? 0;
      const isSelected =
        !!selected &&
        normalizeWidth(selected.word) === key &&
        selected.chunkIndex === chunkIndex &&
        selected.localIndex === count;
      localCounter[key] = count + 1;
      if (isSelected) {
        return `<span id="selected-highlight" style="background:#FFF1EE;color:#f5222d;font-weight:600;border-bottom:2px solid #FC5353;">${matched}</span>`;
      }
      return `<span style="background:#FFFECA;font-weight:600;border-bottom:2px solid #FFED7B;">${matched}</span>`;
    });
  }

  const navigationMatches = globalMatches.length;
  const totalMatches = useMemo(
    () => (activeTab === 'wrong' ? totalWrongMatches : totalSensitiveMatches),
    [activeTab, totalWrongMatches, totalSensitiveMatches],
  );

  const handlePrev = () => {
    if (navigationMatches <= 1) return;
    setSelectedIndex((prev) => Math.max(prev - 1, 0));
  };
  const handleNext = () => {
    if (navigationMatches <= 1) return;
    setSelectedIndex((prev) => Math.min(prev + 1, navigationMatches - 1));
  };

  // 生成用于展示的分段列表：若 chunkIndex 不连续则插入“此段省略”占位
  const displayTrunks = useMemo(() => {
    const trunks = currentTrunks || [];
    if (!trunks.length) return [] as any[];
    // 重复文档预览没有 chunkIndex，不处理
    const hasChunkIndex = trunks.some((c: any) => typeof c?.chunkIndex === 'number');
    if (!hasChunkIndex) return trunks as any[];

    const sorted = [...trunks].sort((a: any, b: any) => (a.chunkIndex || 0) - (b.chunkIndex || 0));
    const res: any[] = [];
    for (let i = 0; i < sorted.length; i++) {
      const cur = sorted[i];
      res.push(cur);
      const next = sorted[i + 1];
      if (next && (next.chunkIndex || 0) !== (cur.chunkIndex || 0) + 1) {
        res.push({ _id: `omitted-${cur._id}-${i}`, omitted: true });
      }
    }
    return res;
  }, [currentTrunks]);

  // 原始 _id 到索引的映射，保持高亮计数一致
  const chunkIdToIndex = useMemo(() => {
    const map: Record<string, number> = {};
    (currentTrunks || []).forEach((c: any, idx: number) => {
      if (c && c._id) map[c._id] = idx;
    });
    return map;
  }, [currentTrunks]);

  const tabItems = useMemo(() => {
    const items: Array<{ key: 'sensitive' | 'wrong' | 'repetition'; label: JSX.Element }> = [];
    optimizeTypes.forEach((t) => {
      if (String(t).includes('敏感词') && hasSensitive) {
        items.push({
          key: 'sensitive',
          label: (
            <div className="flex items-center">
              <SvgIcon icon="document-ic3" size={16} className="mr-1" /> 敏感词 (
              {totalSensitiveMatches})
            </div>
          ),
        });
      }
      if (String(t).includes('错别字') && hasWrong) {
        items.push({
          key: 'wrong',
          label: (
            <div className="flex items-center">
              <SvgIcon icon="document-ic3" size={16} className="mr-1" /> 错别字 ({totalWrongMatches}
              )
            </div>
          ),
        });
      }
    });
    if (items.length === 0) {
      if (hasSensitive)
        items.push({
          key: 'sensitive',
          label: (
            <div className="flex items-center">
              <SvgIcon icon="document-ic3" size={16} className="mr-1" /> 敏感词 (
              {totalSensitiveMatches})
            </div>
          ),
        });
      if (hasWrong)
        items.push({
          key: 'wrong',
          label: (
            <div className="flex items-center">
              <SvgIcon icon="document-ic3" size={16} className="mr-1" /> 错别字 ({totalWrongMatches}
              )
            </div>
          ),
        });
    }
    if (hasRepetition) {
      items.push({
        key: 'repetition',
        label: (
          <div className="flex items-center">
            <SvgIcon icon="document-ic3" size={16} className="mr-1" /> 重复文件 (
            {repetitionDataList.length})
          </div>
        ),
      });
    }
    return items;
  }, [
    optimizeTypes,
    hasSensitive,
    hasWrong,
    hasRepetition,
    sensitiveList.length,
    wronglyList.length,
    repetitionDataList.length,
    totalSensitiveMatches,
    totalWrongMatches,
  ]);

  useEffect(() => {
    if (!hasSensitive && activeTab === 'sensitive') setActiveTab(hasWrong ? 'wrong' : 'repetition');
    if (!hasWrong && activeTab === 'wrong') setActiveTab(hasSensitive ? 'sensitive' : 'repetition');
    if (!hasRepetition && activeTab === 'repetition')
      setActiveTab(hasSensitive ? 'sensitive' : 'wrong');
  }, [hasSensitive, hasWrong, hasRepetition]);

  const hasData = useMemo(() => {
    if (optimizeTypes.length > 1) {
      return <div>文档存在多处待改善问题</div>;
    }
    if (optimizeTypes.length === 1) {
      return (
        <div className="flex items-center gap-6">
          {hasWrong && <div>文档存在多处错别字</div>}
          {hasSensitive && <div>文档存在多处敏感词</div>}
          {repetitionDataList.length > 0 && <div>文档存在重复文件</div>}
        </div>
      );
    }
    return <div>文档无待改善问题</div>;
  }, [
    optimizeTypes,
    hasWrong,
    hasSensitive,
    totalWrongMatches,
    totalSensitiveMatches,
    repetitionDataList.length,
  ]);

  return (
    <div>
      <div className=" flex h-10 w-full items-center justify-between rounded-xl border border-[#FFB569] bg-functional-orange px-2 ">
        <div className="flex items-center gap-3 font-semibold">
          <SvgIcon icon="document-ic4" size={16} className="" />
          {hasData}
        </div>
        <div className="cursor-pointer text-primary" onClick={() => setShowTitle(!showTitle)}>
          {showTitle && <SvgIcon icon="document-ic5" size={16} className=" mr-1" />}
          {showTitle ? '返回预览模式' : '查看详情'}
        </div>
      </div>
      <div className="mb-2">
        {showTitle && (
          <div className=" h-[94x]">
            {(hasSensitive || hasWrong || hasRepetition) && showTitle && (
              <AntdTabs
                items={tabItems}
                activeKey={activeTab}
                onChange={(k) => setActiveTab(k as 'sensitive' | 'wrong' | 'repetition')}
              />
            )}
            {showTitle && (hasSensitive || hasWrong || hasRepetition) && (
              <div className="flex cursor-pointer items-center gap-2 text-@brand-color">
                {activeTab !== 'repetition' && (
                  <Button
                    size="small"
                    type="default"
                    className={`!border !border-line-2 !bg-fill-1 ${
                      navigationMatches <= 1 || selectedIndex === 0 ? '!text-text-2' : ''
                    }`}
                    disabled={navigationMatches <= 1 || selectedIndex === 0}
                    onClick={(e) => {
                      e.stopPropagation();
                      handlePrev();
                    }}
                  >
                    上一步
                  </Button>
                )}
                {activeTab !== 'repetition' && (
                  <span className="text-text-3">
                    {totalMatches > 0 ? selectedIndex + 1 : 0}/{totalMatches}
                  </span>
                )}
                {activeTab !== 'repetition' && (
                  <Button
                    size="small"
                    type="default"
                    className={`!border !border-line-2 !bg-fill-1 ${
                      navigationMatches <= 1 || selectedIndex >= navigationMatches - 1
                        ? '!text-text-2'
                        : ''
                    }`}
                    disabled={navigationMatches <= 1 || selectedIndex >= navigationMatches - 1}
                    onClick={(e) => {
                      e.stopPropagation();
                      handleNext();
                    }}
                  >
                    下一步
                  </Button>
                )}
              </div>
            )}
          </div>
        )}
      </div>

      {showTitle && activeTab !== 'repetition' && (hasSensitive || hasWrong) && (
        <div className="h-[510px] w-[770px]">
          <div className="h-full  overflow-auto rounded-xl bg-bg-3 p-4" ref={previewRef}>
            {displayTrunks.map((chunk: any, idx: number) => {
              if (chunk.omitted) {
                return (
                  <div key={chunk._id || `omitted-${idx}`} className="my-6">
                    <div className="flex items-center text-text-2">
                      <div className="flex-1 border-t border-dashed border-line-2" />
                      <div className="mx-4 text-sm">此段省略</div>
                      <div className="flex-1 border-t border-dashed border-line-2" />
                    </div>
                  </div>
                );
              }
              const origIdx = chunkIdToIndex[chunk._id] ?? idx;
              return (
                <div key={chunk._id || idx} className="mb-6">
                  <Markdown source={highlightText(chunk.text, origIdx)} />
                </div>
              );
            })}
          </div>
        </div>
      )}
      {showTitle && activeTab === 'repetition' && hasRepetition && (
        <div className="h-[536px]">
          <div className="h-full overflow-auto rounded-xl bg-bg-3 p-4">
            {(repetitionDataList || []).map((item: any, index: number) => (
              <div key={item._id || index} className="mb-4 flex py-3 ">
                <div className="pr-3 font-extrabold">
                  {index + 1 > 9 ? index + 1 : `0${index + 1}`}
                </div>
                <div className="min-w-0">
                  <div className="flex items-center">
                    <div>文件位置：</div>
                    <div className="ml-1 w-[600px] truncate text-gray-600">
                      {item.datasetPath}/{item.name}
                    </div>
                  </div>
                  <div className="mt-2 text-sm text-text-4">
                    <div className="mb-2 mr-4">
                      <span>创建时间：</span>
                      {formatData(item.createTime)}
                    </div>
                    <div>
                      <span>创建人：</span>
                      {item.username}
                    </div>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

export default DocumentMessage;
